home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / GL / libdemo / event.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  297 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    event.c
  19.  *    A more rational way to handle reading the event queue
  20.  * Written by Wade Olsen
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <device.h>
  25. #include "event.h"
  26. #ifdef spaceball
  27. #include <gl/spaceball.h>
  28. #endif
  29.  
  30. int context, state, device;
  31.  
  32. typedef struct event_s
  33. {
  34.     int        window, device, state;
  35.     void (*func)(void *, int);
  36.     void *arg;
  37.     struct event_s    *next;
  38. } event_t, *event_p;
  39.  
  40. typedef struct update_s
  41. {
  42.     int *flag;
  43.     void (*ufunc)(void *);
  44.     void *arg;
  45.     struct update_s *next;
  46. } update_t, *update_p;
  47.  
  48.  
  49. static event_p        event_list;
  50. static update_p    update_list;
  51.  
  52. /*
  53.  * This routine adds an event to be checked for to the event queue.
  54.  * window should be the wid of the window to respond in, or ANY if
  55.  * this event applies to all windows.  device is the device, and state
  56.  * is the device's value (e.g.  ANY, UP, DOWN, the window id (for
  57.  * REDRAW), etc).  Func is the function that will be called, with
  58.  * arguments 'arg' and the device's value.
  59.  * 
  60.  * NOTE:  the device must be queued for it to be found by the event()
  61.  * routine-- add_event DOES NOT qdevice(device).
  62.  */
  63. void
  64. add_event(int window, int device, int state, 
  65.     void (*func)(void *, int), void *arg)
  66. {
  67.     event_p new_guy;
  68.  
  69.     new_guy = (event_p)malloc(sizeof(event_t));
  70.     new_guy->window = window;
  71.     new_guy->device = device;
  72.     new_guy->state  = state;
  73.     new_guy->func   = func;
  74.     new_guy->arg    = arg;
  75.     new_guy->next   = event_list;
  76.     event_list = new_guy;
  77. }
  78.  
  79. /*
  80.  *    Specify a function to be called if there is nothing in the queue
  81.  * and (*flag) is non-zero.  If no update function is active, or
  82.  * (*flag) is 0, then event() will block on a qread.  If there is an
  83.  * active update function, event() will continuously call the update
  84.  * function, hogging the cpu.
  85.  */
  86. void
  87. add_update(int *flag, void (*ufunc)(void *), void *arg)
  88. {
  89.     update_p    new_guy;
  90.  
  91.     new_guy = (update_p)malloc(sizeof(update_t));
  92.     new_guy->flag = flag;
  93.     new_guy->ufunc = ufunc;
  94.     new_guy->arg  = arg;
  95.     new_guy->next = update_list;
  96.     update_list = new_guy;
  97. }
  98.  
  99. void find_event(void);
  100. int do_updates(void);
  101. void event_inputchange(void);
  102.  
  103. static void
  104. initialize()
  105. {
  106.     static int initialized = 0;
  107.  
  108.     if (initialized == 0)
  109.     {
  110.         add_event(ANY, INPUTCHANGE, ANY, event_inputchange, NULL);
  111.         qdevice(INPUTCHANGE);
  112.         initialized = 1;
  113.     }
  114. }
  115.  
  116.  
  117. /*
  118.  * The main Event.  Call this repeatedly to automagically handle
  119.  * reading the queue, and calling your functions to handle what
  120.  * appears there.
  121.  */
  122. void
  123. event()
  124. {
  125.     initialize();
  126.  
  127.     /* Something in the queue?  Handle it */
  128.     if (qtest())
  129.     while (qtest())
  130.         find_event();
  131.     /*
  132.      * Or, if there's no update function, wait for something to appear
  133.      */
  134.     else if (do_updates() == 0)
  135.     find_event();
  136. }
  137.  
  138. /*
  139.  * Similar to event, but does not block if there are no events
  140.  */
  141. void
  142. event_noblock()
  143. {
  144.     initialize();
  145.  
  146.     /* Something in the queue?  Handle it */
  147.     while (qtest())
  148.     find_event();
  149.  
  150.     /*
  151.      * Or, if there's no update function, wait for something to appear
  152.      */
  153.     do_updates();
  154. }
  155.  
  156. static int
  157. do_updates()
  158. {
  159.     update_p    scan;
  160.     int        updated = 0;
  161.  
  162.     for (scan = update_list; scan; scan = scan->next)
  163.     {
  164.         if (*scan->flag)
  165.         {
  166.             (*scan->ufunc)(scan->arg);
  167.             updated = 1;
  168.         }
  169.     }
  170.  
  171.     return(updated);
  172. }
  173.  
  174. static void
  175. event_inputchange()
  176. {
  177.     context = state;
  178. #ifdef spaceball
  179.     sbEvent(INPUTCHANGE, state);
  180. #endif
  181. }
  182.  
  183. void
  184. find_event()
  185. {
  186.     int flag;
  187.     event_p scan;
  188.     short s;
  189.  
  190.     device = qread(&s);
  191.     state = s;
  192.     for (scan = event_list, flag=0; scan; scan = scan->next)
  193.     {
  194.         if ( ((scan->window == ANY) || (context == scan->window))
  195.             && ((scan->device == ANY) ||(device == scan->device))
  196.             && ((scan->state == ANY) || (state == scan->state)))
  197.         {
  198.             (*scan->func)(scan->arg, state);
  199.             flag = 1;
  200.         }
  201.     }
  202. #ifdef spaceball
  203.     if (flag == 0)
  204.         sbEvent(device, s);
  205. #endif
  206. }
  207.  
  208. /*
  209.  * Delete event handlers
  210.  */
  211.  
  212. void
  213. delete_events(int context, int device, int state, void *func)
  214. {
  215.     event_p scan, prev;
  216.  
  217.     prev = 0;
  218.     scan = event_list; 
  219.     while (scan)
  220.     {
  221.         if (       ((context == ANY) || (context == scan->window))
  222.             && ((device == ANY) || (device == scan->device))
  223.             && ((state == ANY) || (state == scan->state))
  224.             && ((func == (void *)ANY) || (func == scan->func)))
  225.         {
  226.             event_p nuke;
  227.  
  228.             nuke = scan;
  229.             
  230.             if (prev)
  231.             scan = prev->next = scan->next;
  232.             else
  233.             scan = event_list = scan->next;
  234.  
  235.             free(nuke);
  236.         }
  237.         else
  238.         {
  239.             prev = scan;
  240.             scan = scan->next;
  241.         }
  242.     }
  243. }
  244.  
  245.  
  246. void
  247. delete_updates(int * flag, void * func)
  248. {
  249.     update_p    scan, prev;
  250.  
  251.     prev = 0;
  252.     scan = update_list;
  253.     while (scan)
  254.     {
  255.         if (    ((flag == scan->flag) || (flag == (int *)ANY))
  256.              && ((func == scan->ufunc) || (func == (void *)ANY)))
  257.         {
  258.             update_p nuke;
  259.  
  260.             nuke = scan;
  261.  
  262.             if (prev)
  263.             scan = prev->next = scan->next;
  264.             else
  265.             scan = update_list = scan->next;
  266.  
  267.             free(nuke);
  268.         }
  269.         else
  270.         {
  271.             prev = scan;
  272.             scan = scan->next;
  273.         }
  274.     }
  275. }
  276.  
  277.  
  278. /*
  279.  * Misc. event handlers
  280.  */
  281.  
  282. void setInt(void * i)
  283. {
  284.     *(int *)i = 1;
  285. }
  286.  
  287. void resetInt(void * i)
  288. {
  289.     *(int *)i = 0;
  290. }
  291.  
  292. void setIntToVal(void * i, int v)
  293. {
  294.     *(int *)i = v;
  295. }
  296.  
  297.